home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / libc / Net_InetChecksum.c < prev    next >
C/C++ Source or Header  |  1990-09-11  |  4KB  |  158 lines

  1. /* 
  2.  * Net_InetChecksum.c --
  3.  *
  4.  *    Compute an internet checksum.
  5.  *
  6.  * Copyright 1987 Regents of the University of California
  7.  * All rights reserved.
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/lib/net/RCS/Net_InetChecksum.c,v 1.5 90/09/11 14:43:46 kupfer Exp $ SPRITE (Berkeley)";
  19. #endif not lint
  20.  
  21.  
  22. #include "sprite.h"
  23. #include "net.h"
  24.  
  25. /*
  26.  *----------------------------------------------------------------------
  27.  *
  28.  * Net_InetChecksum --
  29.  *
  30.  *    Compute the 16-bit one's complement of the 1's complement sum of
  31.  *    of all words in the buffer.
  32.  *
  33.  *    Note: It is assumed that the length of the buffer is at most
  34.  *    128K bytes long. It also helps if the buffer is word-aligned.
  35.  *
  36.  * Results:
  37.  *    The 1's complement checksum in network byte-order.
  38.  *
  39.  * Side effects:
  40.  *    None.
  41.  *
  42.  *----------------------------------------------------------------------
  43.  */
  44.  
  45. unsigned short
  46. Net_InetChecksum(len, bufPtr)
  47.     register int len;        /* The number of bytes to checksum. */
  48.     Address bufPtr;        /* What to checksum. */
  49. {
  50.     register unsigned short *wordPtr = (unsigned short *) bufPtr;
  51.     register unsigned int sum = 0;
  52.  
  53.     
  54.     /*
  55.      * The basic algorithm 16-bit 1's complement addition is 
  56.      *  1) add the two unsigned 16-bit quantities, 
  57.      *  2) if there was a carry out of the high-order bit, 
  58.      *       it is added to the sum.
  59.      * To detect a carry out of the high-order bit, the sum is stored
  60.      * in a 32-bit word. As an optimization, we delay step 2 until
  61.      * all the words have been added together. At that point, the
  62.      * upper-half of the sum contains the sum of the carries from the
  63.      * additions. This value is then added to the lower half and if that
  64.      * operation causes a carry, then 1 is added to the sum.
  65.      *
  66.      * The optimization does place a limit on how many bytes can be
  67.      * summed without causing an overflow of the 32-bit sum. In the worst
  68.      * case, a maximum of 64K additions of 16-bit values can be added
  69.      * without overflow.
  70.      * 
  71.      * The summation is done in an unrolled loop. Once we have less than 
  72.      * 32 bytes to sum then it must be done in smaller loops.
  73.      */
  74.  
  75.     if (len == 20) {
  76.     sum += *wordPtr++;
  77.     sum += *wordPtr++;
  78.     sum += *wordPtr++;
  79.     sum += *wordPtr++;
  80.     sum += *wordPtr++;
  81.  
  82.     sum += *wordPtr++;
  83.     sum += *wordPtr++;
  84.     sum += *wordPtr++;
  85.     sum += *wordPtr++;
  86.     sum += *wordPtr++;
  87.     } else {
  88.     while (len >= 32) {
  89.         sum += *wordPtr++;
  90.         sum += *wordPtr++;
  91.         sum += *wordPtr++;
  92.         sum += *wordPtr++;
  93.  
  94.         sum += *wordPtr++;
  95.         sum += *wordPtr++;
  96.         sum += *wordPtr++;
  97.         sum += *wordPtr++;
  98.  
  99.         sum += *wordPtr++;
  100.         sum += *wordPtr++;
  101.         sum += *wordPtr++;
  102.         sum += *wordPtr++;
  103.  
  104.         sum += *wordPtr++;
  105.         sum += *wordPtr++;
  106.         sum += *wordPtr++;
  107.         sum += *wordPtr++;
  108.  
  109.         len -= 32;
  110.     }
  111.     while (len >= 2) {
  112.         sum += *wordPtr++;
  113.         len -= 2;
  114.     }
  115.  
  116.     if (len == 1) {
  117. #if BYTE_ORDER == LITTLE_ENDIAN
  118.         sum += (*wordPtr) & 0x00ff;
  119. #else
  120.         sum += (*wordPtr) & 0xff00;
  121. #endif
  122.     }
  123.     }
  124.  
  125.     /*
  126.      * The most signficant bits of "sum" contains the carries from
  127.      * the overflow of the summing. Add this overflow back into
  128.      * the least significant 16 bits of the sum and do it a second
  129.      * time in case there's a carry from the first time.
  130.      */
  131.     if (sum > 0xffff) {
  132. #if 0
  133.     extern int main_Debug, tcp_out;
  134.  
  135.     if (tcp_out && main_Debug) {
  136.         fprintf(stderr, "Checksum 1: %x\n", sum);
  137.     }
  138. #endif /* 0 */
  139.  
  140.     sum = ((sum >> 16) & 0xffff) + (sum & 0xffff);
  141.     /*
  142.      * See if there was a carry from the addition. The overflow will
  143.      * be at most 1.
  144.      */
  145. #if 0
  146.     if (tcp_out && main_Debug) {
  147.         fprintf(stderr, "Checksum 2: %x\n", sum);
  148.     }
  149. #endif /* 0 */
  150.     if (sum > 0xffff) {
  151.         sum++;
  152.     }
  153.     }
  154.  
  155.     return((~sum & 0xffff));
  156. }
  157.  
  158.